/* Picaroon Creature definitions */

import {
	"container/heap"
	}



type Aiflag uint16

const (
	AI_IMMOBILE Aiflag = 1 << iota
	AI_
	AI_PLAYER //this is the player character
)

type CreatureClass uint8

const (
	CC_PICAROON CreatureClass = iota
	CC_SLIME
)

type Inventory []item //so we can write interfaces for it to autostack items etc

type Creature struct {
	strength, health, speed, defence uint8
	inventory Inventory //all creatures have
	weapon	item
	armour	item
	ring	[2]item
	aiflags Aiflag   //behavior qualifiers - can be changed by events in the game (paralysis potions etc)
	class	CreatureClass //intrinsic Creature Class, can only be changed by, say, Polymorph
	nextAct	uint32 //might need to be bigger, depending on how big our ticks are
	index i
}

//although better via an interface type - for method accessors for Status, Inventory etc

type CreatureView interface {
	Strength() 	uint8
	Health()	uint8
	Speed()		uint8
	Defence() 	uint8
	Inventory()	Inventory //actually, this should probably be a map or a lightweight interface (handles stacking, assignment of slots etc)
	Weapon()	item
	Armour()	item
	Rings()		[2]item
	Class()		CreatureClass
	//consider a "next action" accessor that returns a nice version of the next action timestamp (for advanced AI tactics?)
}

func (c Creature) Strength() uint8 {
	return c.strength
}
func (c Creature) Health() uint8 {
	return c.health
}
func (c Creature) Speed() uint8 {
	return c.speed
}
func (c Creature) Defence() uint8 {
	return c.defence
}
func (c Creature) Inventory() uint8 {
	return c.inventory
}
func (c Creature) Weapon() item {
	return c.weapon //sure?
}
func (c Creature) Armour() item {
	return c.armour
}
func (c Creature) Rings() [2]item {
	return c.ring
}
func (c Creature) Class() CreatureClass {
	return c.class
}


type CreatureCtrl interface {
	CreatureView
	Set...
	}

//action queue code stolen liberally from example Golang PriorityQueue from heap package
type ActionQueue []*Creature
func (aq ActionQueue) Less(i, j int) bool {
	return aq[i].NextAct > aq[j].NextAct
}
func (aq ActionQueue) Swap(i, j int) {
	aq[i], aq[j] = aq[j], aq[i]
	aq[i].index = i
	aq[j].index = j
}
func (aq ActionQueue) Len() int { return len(aq) }
func (aq *ActionQueue) Push( x interface{}) {
	a := *aq
	n := len(a)
	a = a[0 : n+1]
	item := x.(*Item)
	item.index = n
	a[n] = item
	*pq = a
}
func (aq *ActionQueue) Pop() interface{} {
	a := *aq
	n := len(a)
	item := a[n-1]
	item.index = -1 //prevents us from breaking the queue by assuming item is still in it
	*aq = a[0 : n-1]
	return item
}

// modified from the update function in the example - this takes the next eligible creature in the queue, does their AI
// (which returns the NextAct (time of their next action) and the results of their action (most pertinently - if they are DEAD) )
// if they're not DEAD, then we put them back in the queue ordered by their next action time.
// Optimisations: do all actions take Speed time to complete? If so, then DoAI is trivial as it doesn't need to specify NextAct - it's just the current NextAct + c.speed
// -> problem with dealing with paralysis etc though in that case
func (aq *ActionQueue) update(NextAct uint32) {
	item := heap.Pop(aq).(*Creature)
	NextAct, result = item.DoAI()
	if result != R_DEAD {
		item.NextAct = NextAct
		heap.Push(aq, item)
	}
}

// changePriority is not used by the example but shows how to change the
// priority of an arbitrary item. (we might use this to handle, for example, zapping with a wand of slowness or speed, or paralysis)
func (aq *ActionQueue) changePriority(item *Creature, NextAct uint32) {
    heap.Remove(aq, item.index)
    item.NextAct = NextAct
    heap.Push(aq, item)
}

 //or however we implement a priority queue of Creatures who get to act next (probably better to have a slice of Creatures and a queue of their indexes, or just a queue of pointers to them (to avoid the whole "Creatures dies, messing up indexes in slice" issue)
